package com.jdy.haoduoaiteacher.view;

import android.annotation.SuppressLint;
import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.LinearInterpolator;
import android.view.animation.RotateAnimation;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;

import com.ycsj.goldmedalnewconcept.R;

import java.util.Date;

@SuppressLint("InflateParams")
public class RefreshListview extends ListView implements OnScrollListener{
  
  private final static int RELEASE_To_REFRESH = 0;// 下拉过程的状态值  
  private final static int PULL_To_REFRESH = 1; // 从下拉返回到不刷新的状态值  
  private final static int REFRESHING = 2;// 正在刷新的状态值  
  private final static int DONE = 3;  
  private final static int LOADING = 4;  

  // 实际的padding的距离与界面上偏移距离的比例  
  private final static int RATIO = 3;  
  private LayoutInflater inflater;    //  用于 加载 布局文件

  // ListView头部下拉刷新的布局  
  private LinearLayout headerView;  
  private TextView lvHeaderTipsTv;  
  private TextView lvHeaderLastUpdatedTv;  
  private ImageView lvHeaderArrowIv;  //  动画  箭头
  private ProgressBar lvHeaderProgressBar;   // 加载 转动

  // 定义头部下拉刷新的布局的高度  
  private int headerContentHeight;  

  private RotateAnimation animation;    //  下拉动画
  private RotateAnimation reverseAnimation;   // 回复动画

  private int startY;    //   记录点击的 位置
  private int state;    //  状态
  private boolean isBack;   // 是否 返回
  private int firstItemIndex;
  private int lastItem;
  // 用于保证startY的值在一个完整的touch事件中只被记录一次  
  private boolean isRecored;   //   是否 已经 记录 过了

  private OnRefreshListener refreshListener;    // 刷新 监听器

  private boolean isRefreshable;    // 是否刷新 

  //  构造 函数
  public RefreshListview(Context context) {  
      super(context);  
      init(context);  
  }  

  public RefreshListview(Context context, AttributeSet attrs) {  
      super(context, attrs);  
      init(context);  
  }  

  private void init(Context context) {  
      setCacheColorHint(context.getResources().getColor(R.color.background));  //  设置 listview 的 背景   以免 显示的 是 默认背景颜色
      inflater = LayoutInflater.from(context);  
      headerView = (LinearLayout) inflater.inflate(R.layout.listhead, null);  // 加载得到 布局文件 
      
      lvHeaderTipsTv = (TextView) headerView    // 初始化 其中的控件
              .findViewById(R.id.lvHeaderTipsTv);  
      lvHeaderLastUpdatedTv = (TextView) headerView  
              .findViewById(R.id.lvHeaderLastUpdatedTv);  

      lvHeaderArrowIv = (ImageView) headerView  
              .findViewById(R.id.lvHeaderArrowIv);  
      // 设置下拉刷新图标的最小高度和宽度  
      lvHeaderArrowIv.setMinimumWidth(70);  
      lvHeaderArrowIv.setMinimumHeight(50);  

      lvHeaderProgressBar = (ProgressBar) headerView  
              .findViewById(R.id.lvHeaderProgressBar);  
      measureView(headerView);      //  测量 头部 view 的 宽高
      headerContentHeight = headerView.getMeasuredHeight();    // 得到 高  
      // 设置内边距，正好距离顶部为一个负的整个布局的高度，正好把头部隐藏  
      headerView.setPadding(0, -1 * headerContentHeight, 0, 0);  
      // 重绘一下  
      headerView.invalidate();  
      // 将下拉刷新的布局加入ListView的顶部  
      addHeaderView(headerView, null, false);  
      // 设置滚动监听事件  
      setOnScrollListener(this);  

      // 设置旋转动画事件   ------ 下拉动画          180度反转  
      animation = new RotateAnimation(0, -180,  
              RotateAnimation.RELATIVE_TO_SELF, 0.5f,  
              RotateAnimation.RELATIVE_TO_SELF, 0.5f);  
      animation.setInterpolator(new LinearInterpolator());  
      animation.setDuration(250);    // 动画持续 时间
      animation.setFillAfter(true);     // 动画执行完是否停留在执行完的状态

      //  箭头的回复 动画            180度 返回反转
      reverseAnimation = new RotateAnimation(-180, 0,  
              RotateAnimation.RELATIVE_TO_SELF, 0.5f,  
              RotateAnimation.RELATIVE_TO_SELF, 0.5f);  
      reverseAnimation.setInterpolator(new LinearInterpolator());  
      reverseAnimation.setDuration(200);  
      reverseAnimation.setFillAfter(true);  

      // 一开始的状态就是下拉刷新结束的状态，所以为DONE  
      state = DONE;  
      // 是否正在刷新  
      isRefreshable = false;  
  }  

  @Override  
  public void onScrollStateChanged(AbsListView view, int scrollState) {  

  }  

  @Override  
  public void onScroll(AbsListView view, int firstVisibleItem,  
          int visibleItemCount, int totalItemCount) {  
              if (firstVisibleItem == 0) {  // 如果第一个可见条目为0 
                  isRefreshable = true;   //  可以 刷新
               } else {  
                  isRefreshable = false;  //不可刷新
               } 
              firstItemIndex = firstVisibleItem;
              lastItem = firstVisibleItem + visibleItemCount - 1;
      }  

  //  触摸 事件
  @Override  
  public boolean onTouchEvent(MotionEvent ev) {  
      if (isRefreshable) {         // 可以刷新  
          switch (ev.getAction()) {  
          case MotionEvent.ACTION_DOWN:   // 按下手指的时候 
              if (!isRecored) {  //   第一次 记录 按下的 Y位置
                  isRecored = true;      // 设置为 true
                  startY = (int) ev.getY();// 手指按下时记录当前位置  
              }  
              break;  
          case MotionEvent.ACTION_UP:            //  松手的时候
              if (state != REFRESHING && state != LOADING) {  //  并不是 正在刷新状态  也不是 正在加载状态
                  if (state == PULL_To_REFRESH) {     //  下拉 的 程度 不够  导致 没有刷新   
                      state = DONE;   // 就当做是 刷新完成    回到 初始状态  headview 隐藏在上方
                      changeHeaderViewByState();  // 更新 head 状态
                  }  
                  if (state == RELEASE_To_REFRESH) {   //  下拉程度 达到   准备 刷新
                      state = REFRESHING;   // 设置状态为 正在刷新
                      changeHeaderViewByState();  // 更新状态
                      onLvRefresh();    // 刷新操作
                  }  
              }  
              isRecored = false;       // 设置 为  未记录  以便 下次在下拉刷新
              isBack = false;      //

              break;  

          case MotionEvent.ACTION_MOVE:  // 手指 移动过程
              int tempY = (int) ev.getY();  // 记录 Y的 位置
              if (!isRecored) {  //   没有 记录
                  isRecored = true;   
                  startY = tempY;  // 记录 Y
              }  
              if (state != REFRESHING && isRecored && state != LOADING) {  //    如果 不是正在刷新状态 也不是 正在加载状态  且 第一次记录 Y
                  // 保证在设置padding的过程中，当前的位置一直是在head，否则如果当列表超出屏幕的话，当在上推的时候，列表会同时进行滚动  
                  // 可以松手去刷新了  
                  if (state == RELEASE_To_REFRESH) {  
                      setSelection(0);  
                      // 往上推了，推到了屏幕足够掩盖head的程度，但是还没有推到全部掩盖的地步  
                      if (((tempY - startY) / RATIO < headerContentHeight)// 由松开刷新状态转变到下拉刷新状态  
                              && (tempY - startY) > 0) {  
                          state = PULL_To_REFRESH;  
                          changeHeaderViewByState();  
                      }  
                      // 一下子推到顶了  
                      else if (tempY - startY <= 0) {// 由松开刷新状态转变到done状态  
                          state = DONE;  
                          changeHeaderViewByState();  
                      }  
                  }  
                  // 还没有到达显示松开刷新的时候,DONE或者是PULL_To_REFRESH状态  
                  if (state == PULL_To_REFRESH) {  
                      setSelection(0);  
                      // 下拉到可以进入RELEASE_TO_REFRESH的状态  
                      if ((tempY - startY) / RATIO >= headerContentHeight) {// 由done或者下拉刷新状态转变到松开刷新  
                          state = RELEASE_To_REFRESH;  
                          isBack = true;  
                          changeHeaderViewByState();  
                      }  
                      // 上推到顶了  
                      else if (tempY - startY <= 0) {// 由DOne或者下拉刷新状态转变到done状态  
                          state = DONE;  
                          changeHeaderViewByState();  
                      }  
                  }  
                  // done状态下  
                  if (state == DONE) {  
                      if (tempY - startY > 0) {  
                          state = PULL_To_REFRESH;  
                          changeHeaderViewByState();  
                      }  
                  }  
                  // 更新headView的size  
                  if (state == PULL_To_REFRESH) {  
                      headerView.setPadding(0, -1 * headerContentHeight  
                              + (tempY - startY) / RATIO, 0, 0);  

                  }  
                  // 更新headView的paddingTop  
                  if (state == RELEASE_To_REFRESH) {  
                      headerView.setPadding(0, (tempY - startY) / RATIO  
                              - headerContentHeight, 0, 0);  
                  }  

              }  
              break;  

          default:  
              break;  
          }  
      }  
      return super.onTouchEvent(ev);  
  }  

  // 当状态改变时候，调用该方法，以更新界面  
  private void changeHeaderViewByState() {  
      switch (state) {  
      case RELEASE_To_REFRESH:  
          lvHeaderArrowIv.setVisibility(View.VISIBLE);  
          lvHeaderProgressBar.setVisibility(View.GONE);  
          lvHeaderTipsTv.setVisibility(View.VISIBLE);  
          lvHeaderLastUpdatedTv.setVisibility(View.VISIBLE);  

          lvHeaderArrowIv.clearAnimation();// 清除动画  
          lvHeaderArrowIv.startAnimation(animation);// 开始动画效果  

          lvHeaderTipsTv.setText("松开刷新");  
          break;  
      case PULL_To_REFRESH:  
          lvHeaderProgressBar.setVisibility(View.GONE);  
          lvHeaderTipsTv.setVisibility(View.VISIBLE);  
          lvHeaderLastUpdatedTv.setVisibility(View.VISIBLE);  
          lvHeaderArrowIv.clearAnimation();  
          lvHeaderArrowIv.setVisibility(View.VISIBLE);  
          // 是由RELEASE_To_REFRESH状态转变来的  
          if (isBack) {  
              isBack = false;  
              lvHeaderArrowIv.clearAnimation();  
              lvHeaderArrowIv.startAnimation(reverseAnimation);  

              lvHeaderTipsTv.setText("下拉刷新");  
          } else {  
              lvHeaderTipsTv.setText("下拉刷新");  
          }  
          break;  

      case REFRESHING:  

          headerView.setPadding(0, 0, 0, 0);  

          lvHeaderProgressBar.setVisibility(View.VISIBLE);  
          lvHeaderArrowIv.clearAnimation();  
          lvHeaderArrowIv.setVisibility(View.GONE);  
          lvHeaderTipsTv.setText("正在刷新...");  
          lvHeaderLastUpdatedTv.setVisibility(View.VISIBLE);  
          break;  
      case DONE:  
          headerView.setPadding(0, -1 * headerContentHeight, 0, 0);  

          lvHeaderProgressBar.setVisibility(View.GONE);  
          lvHeaderArrowIv.clearAnimation();  
          lvHeaderArrowIv.setImageResource(R.drawable.arrow_downs);  
          lvHeaderTipsTv.setText("下拉刷新");  
          lvHeaderLastUpdatedTv.setVisibility(View.VISIBLE);  
          break;  
      }  
  }  

  // 此方法直接照搬自网络上的一个下拉刷新的demo，此处是“估计”headView的width以及height  
  @SuppressWarnings("deprecation")
private void measureView(View child) {  
      ViewGroup.LayoutParams params = child.getLayoutParams();  
      if (params == null) {  
          params = new ViewGroup.LayoutParams(  
                  ViewGroup.LayoutParams.FILL_PARENT,  
                  ViewGroup.LayoutParams.WRAP_CONTENT);  
      }  
      int childWidthSpec = ViewGroup.getChildMeasureSpec(0, 0 + 0,  
              params.width);  
      int lpHeight = params.height;  
      int childHeightSpec;  
      if (lpHeight > 0) {  
          childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight,  
                  MeasureSpec.EXACTLY);  
      } else {  
          childHeightSpec = MeasureSpec.makeMeasureSpec(0,  
                  MeasureSpec.UNSPECIFIED);  
      }  
      child.measure(childWidthSpec, childHeightSpec);  
  }  

  public void setonRefreshListener(OnRefreshListener refreshListener) {  
      this.refreshListener = refreshListener;  
      isRefreshable = true;  
  }  

  public interface OnRefreshListener {  
      public void onRefresh();  
  }  

  @SuppressWarnings("deprecation")
public void onRefreshComplete() {  
      state = DONE;  
      lvHeaderLastUpdatedTv.setText("最近更新:" + new Date().toLocaleString());  
      changeHeaderViewByState();  
  }  

  //   正在刷新的 时候 要执行的 刷新事件  接口
  private void onLvRefresh() {  
      if (refreshListener != null) {  
          refreshListener.onRefresh();  
      }  
  }  


}
